#include "CFastTempHome.h"

CFastTempHome::CFastTempHome()
{
	init();
}


CFastTempHome::~CFastTempHome()
{
}

void CFastTempHome::init()
{
	sx = 0, sy = 0, sxy = 0, sxx = 0, ln = 0, guzhang = 0;                   // 最小二乘相关变量
	lastwendu_hj = 0, lastchafen_hj = -100, chushiwendu_hj = -100, chushichafen1_hj = 0;   // 环境温度相关变量
	lastwendu_tb = 0, lastchafen_tb = -100, chushiwendu_tb = -100, chushichafen1_tb = 0, chushichafen2_tb = 0;     // 体表温度相关变量
	maxwendu = 0, maxwencha = 0, buchangxishu = 0, finyucewendu = 0;             // 循环、判断相关变量
	flag = 0, jishu = 0, jishu0 = 0, jishu1 = 0;
	flag_stage = 0, flag_error = 0, temple = 0;

}

float CFastTempHome::MYLOG(float a)
{
	int N = 100;//我们取了前15+1项来估算
	int k, nk;
	float x, xx, y;
	x = (a - 1) / (a + 1);
	xx = x * x;
	nk = 2 * N + 1;
	y = 1.0 / nk;
	for (k = N; k > 0; k--)
	{
		nk = nk - 2;
		y = 1.0 / nk + xx * y;

	}
	return 2.0 * x * y;
}

float CFastTempHome::mydaoshu(float a)
{
	float result = 1 / a;
	return result;
}

float CFastTempHome::myexp(float a)
{
	int k = 20;
	float result = 1 + a;
	for (int i = 0; i < k; i++)
	{
		float fenzi = 1, fenmu = 1;
		for (int j = 1; j < i + 3; j++)
		{
			fenzi = fenzi * a;
			fenmu = fenmu * j;
		}
		float mm = mydaoshu(fenmu);
		result = result + fenzi * mm;
	}
	return result;
}

int CFastTempHome::Stable(float (*TempBuffPoint)[4], int length, int last)
{
	// 如果数组长度小于60，直接返回0
	if (length < 60) return 0;

	float sum = 0;
	int k;

	// 从last位置开始计算，确保位置在数组范围内
	int position1 = (last + 59) % length;
	int position2 = (last + 88) % length;

	// 累加连续60个数据点的第四个元素值
	for (k = 0; k < 30; k++)
	{
		position1 = (position1 + 1) % length; // 更新位置，实现环绕
		position2 = (position2 + 1) % length; // 更新位置，实现环绕
		if (TempBuffPoint[position2][1] - TempBuffPoint[position1][1] < 0)
		{
			sum += (TempBuffPoint[position1][1] - TempBuffPoint[position2][1]); // 累加值
		}
		else
		{
			sum += (TempBuffPoint[position2][1] - TempBuffPoint[position1][1]); // 累加值
		}
	}

	// 计算平均值
	float mean = sum / 30;

	// 判断平均值是否小于0.05
	if (mean < 0.05)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

float CFastTempHome::kuaisushengwen(float tibiaowendu, float huanjingwendu, int type_use)
{
	float shijiwendu = 0;
	float cha_tb, cha_hj;
	float yucewendu;
	float au, ad, a, bu, bd, b;
	int fix_jishu = 30;//开始显示预测数值的最初时刻
	float piancha = 0.15;// 测量偏差阈值，小于该阈值可认为是测量偏差造成的

	float Paras[11];
	for (int i = 0; i < 11; i++)
	{
		if (type_use == 0)
		{
			Paras[i] = Paras_home[i];
		}
		else
		{
			Paras[i] = Paras_hosp[i];
		}

	}
	// 更新最高温度，用于后面的降温流程
	flag_stage = 0;
	if (tibiaowendu > maxwendu)
	{
		maxwendu = tibiaowendu;
	}
	// 若第1次调用该程序，初始化参数并返回tibiaowendu的数据
	if (chushiwendu_tb == -100)
	{
		chushiwendu_tb = tibiaowendu;
		lastwendu_tb = tibiaowendu;
		lastwendu_hj = huanjingwendu;
		shijiwendu = tibiaowendu;
	}
	else
		// 若不是第1次调用该程序，需要首先确定升温数据起点
		// 计算当前的体表和环境的温度差分        
	{
		cha_tb = tibiaowendu - lastwendu_tb;
		if (cha_tb < 0.4 && flag == 0)
		{
			shijiwendu = tibiaowendu;
			lastwendu_tb = tibiaowendu;
			lastwendu_hj = huanjingwendu;
			jishu0 = jishu0 + 1;
		}
		else
		{
			jishu1 = jishu1 + 1;
			cha_hj = huanjingwendu - lastwendu_hj;

			// 根据当前温差是否大于最大温差判断是否到达升温阶段
			// 若当前温差大，则没有到达升温阶段，需要将一些参数归零（因为有可能之前判断到达过升温阶段）
			if (maxwencha < cha_tb)
			{
				maxwencha = cha_tb;// 更新最大温差
				flag = 0;// 重置flag
				jishu = 0;// 重置jishu
				// 重置最小二乘法参数
				sx = 0;
				sy = 0;
				sxx = 0;
				sxy = 0;
				ln = 0;
			}
			// 当前温差小于最大温差且最大温差高于数据偏差，到达了升温阶段
			else
			{
				// 若尚未标记为升温阶段（flag = 1)
				if (flag == 0)
				{
					flag = 1;// 标记为升温阶段
					// 计算各种初始数据(数值补偿时会用到）
					chushiwendu_tb = lastwendu_tb - lastchafen_tb;
					chushichafen1_tb = lastchafen_tb;
					chushichafen2_tb = cha_tb - chushichafen1_tb;

					chushiwendu_hj = lastwendu_hj - lastchafen_hj;
					chushichafen1_hj = lastchafen_hj;
					if ((int)huanjingwendu <= 15 || (int)tibiaowendu <= 15 || (int)huanjingwendu >= 45 || (int)tibiaowendu >= 45 || (int)chushiwendu_tb <= 15 || (int)chushiwendu_tb >= 45 || (int)chushiwendu_hj <= 15 || (int)chushiwendu_hj >= 45)
					{
						flag = 0;
						maxwencha = 0;
						chushiwendu_tb = 0;
						chushichafen1_tb = 0;
						chushichafen2_tb = 0;
						chushiwendu_hj = 0;
						chushichafen1_hj = 0;
					}
					else
					{
						jishu = 3;
						//计算最小二乘法参数
						if (chushichafen1_tb > 0)
						{
							sx = sx + 1.7236;
							sy = sy + MYLOG(lastwendu_tb) + MYLOG(chushiwendu_tb);
							sxx = sxx + 1.4891;
							sxy = sxy + 0.8187 * MYLOG(lastwendu_tb)\
								+ 0.9048 * MYLOG(chushiwendu_tb);
							ln = 2;
							flag_stage = 1;
						}
					}
				}
				// 若已标记升温阶段，但差分结果为负数（表示发生了降温，且已考虑测量噪声），需要取消升温阶段标记，并重置相关参数
				else if (cha_tb < -1 * piancha && tibiaowendu < 32)
				{
					flag_error = 1;
					chushiwendu_tb = 0;
					chushichafen1_tb = 0;
					chushichafen2_tb = 0;

					chushiwendu_hj = 0;
					chushichafen1_hj = 0;

					flag = 0;// 取消升温阶段标记
					jishu = 0;// 重置jishu
					maxwencha = 0;// 重置最大温差
					// 重置最小二乘法参数
					sx = 0;
					sy = 0;
					sxx = 0;
					sxy = 0;
					ln = 0;
				}
			}
			if (flag == 1)
			{
				if ((int)huanjingwendu <= 15 || (int)tibiaowendu <= 15 || (int)huanjingwendu >= 45 || (int)tibiaowendu >= 45)
				{
					shijiwendu = tibiaowendu;
					guzhang = guzhang + 1;
				}
				else
				{
					if (cha_tb <= -1 * piancha && tibiaowendu < 32)
					{
						flag_error = 1;
						chushiwendu_tb = 0;
						chushichafen1_tb = 0;
						chushichafen2_tb = 0;

						chushiwendu_hj = 0;
						chushichafen1_hj = 0;

						flag = 0;// 取消升温阶段标记
						jishu = 0;// 重置jishu
						maxwencha = 0;// 重置最大温差
						guzhang = 0;
						// 重置最小二乘法参数
						sx = 0;
						sy = 0;
						sxx = 0;
						sxy = 0;
						ln = 0;
					}
					else if (jishu <= fix_jishu)
					{
						sx = sx + myexp(-0.1 * (jishu));
						sy = sy + MYLOG(tibiaowendu);
						sxx = sxx + myexp(-0.1 * (jishu)) * myexp(-0.1 * (jishu));
						sxy = sxy + myexp(-0.1 * (jishu)) * MYLOG(tibiaowendu);
						ln = ln + 1;
						if (temple == 0)
						{
							temple = 1;
							flag_stage = 1;
						}
						else
						{
							flag_stage = 2;
						}
					}
					if (jishu < fix_jishu)
					{
						shijiwendu = tibiaowendu;
						jishu = jishu + 1;
					}
					else if (jishu == fix_jishu)
					{
						if (tibiaowendu < 32)
						{
							flag_error = 1;
							shijiwendu = tibiaowendu;
							chushiwendu_tb = 0;
							chushichafen1_tb = 0;
							chushichafen2_tb = 0;
							guzhang = 0;

							chushiwendu_hj = 0;
							chushichafen1_hj = 0;

							flag = 0;// 取消升温阶段标记
							jishu = 0;// 重置jishu
							maxwencha = 0;// 重置最大温差
							// 重置最小二乘法参数
							sx = 0;
							sy = 0;
							sxx = 0;
							sxy = 0;
							ln = 0;
						}
						else
						{
							au = ln * sxy - sx * sy;
							ad = ln * sxx - sx * sx;
							a = (ln * sxy - sx * sy) * mydaoshu(ad);
							bu = sy - a * sx;
							bd = ln;
							b = bu * mydaoshu(bd);
							yucewendu = b;
							if (cha_hj < 0)
							{
								cha_hj = 0;
							}
							if ((yucewendu > 4.5) || (yucewendu < 3.0) || tibiaowendu < chushiwendu_tb + 0.05)
							{
								flag_error = 1;
								flag = 0;
								shijiwendu = tibiaowendu;
								jishu = 0;
								maxwencha = 0;
								maxwendu = 0;
								guzhang = 0;

								sx = 0;
								sy = 0;
								sxx = 0;
								sxy = 0;
								ln = 0;
								buchangxishu = 0;
								finyucewendu = 0;

								chushiwendu_tb = -100;
								chushichafen1_tb = 0;
								chushichafen2_tb = 0;

								chushichafen1_hj = 0;
								chushiwendu_hj = -100;
							}
							else
							{

								buchangxishu = Paras[0] * chushiwendu_tb\
									+ Paras[1] * yucewendu\
									+ Paras[2] * chushichafen1_tb\
									+ Paras[3] * chushichafen2_tb\
									+ Paras[4] * cha_tb\
									+ Paras[5] * (cha_tb - lastchafen_tb)\
									+ Paras[6] * tibiaowendu\
									+ Paras[7] * chushiwendu_hj\
									+ Paras[8] * huanjingwendu\
									+ Paras[9] * chushichafen1_hj\
									+ Paras[10] * cha_hj;
								shijiwendu = buchangxishu;
								finyucewendu = yucewendu;
								jishu = jishu + 1;
								flag_stage = 3;
								temple = 0;
							}
						}
					}
					else
					{
						if (tibiaowendu >= buchangxishu)
						{
							flag_error = 2;
							shijiwendu = tibiaowendu;
							chushiwendu_tb = 0;
							chushichafen1_tb = 0;
							chushichafen2_tb = 0;

							chushiwendu_hj = 0;
							chushichafen1_hj = 0;

							flag = 0;// 取消升温阶段标记
							jishu = 0;// 重置jishu
							maxwencha = 0;// 重置最大温差
							guzhang = 0;
							// 重置最小二乘法参数
							sx = 0;
							sy = 0;
							sxx = 0;
							sxy = 0;
							ln = 0;
						}
						else
						{
							shijiwendu = buchangxishu;
						}
					}
					lastwendu_tb = tibiaowendu;
					lastwendu_hj = huanjingwendu;
					lastchafen_tb = cha_tb;
					lastchafen_hj = cha_hj;
				}

			}
			else
			{
				shijiwendu = tibiaowendu;
				lastwendu_tb = tibiaowendu;
				lastwendu_hj = huanjingwendu;
				lastchafen_tb = cha_tb;
				lastchafen_hj = cha_hj;
			}
			if (jishu > 30 && tibiaowendu < maxwendu - 0.5) //判断是否是下降趋势
			{
				flag_error = 2;
				shijiwendu = tibiaowendu;
				flag = 0;
				jishu = 0;
				maxwencha = 0;
				maxwendu = 0;
				guzhang = 0;

				sx = 0;
				sy = 0;
				sxx = 0;
				sxy = 0;
				ln = 0;
				buchangxishu = 0;
				finyucewendu = 0;

				chushiwendu_tb = -100;
				chushichafen1_tb = 0;
				chushichafen2_tb = 0;
				lastwendu_tb = tibiaowendu;
				lastchafen_tb = -100;


				chushichafen1_hj = 0;
				lastwendu_hj = huanjingwendu;
				lastchafen_hj = -100;
				chushiwendu_hj = -100;
			}
		}
		if (guzhang > 5)
		{
			flag_error = 1;
			shijiwendu = tibiaowendu;
			flag = 0;
			jishu = 0;
			maxwencha = 0;
			maxwendu = 0;
			guzhang = 0;

			sx = 0;
			sy = 0;
			sxx = 0;
			sxy = 0;
			ln = 0;
			buchangxishu = 0;
			finyucewendu = 0;

			chushiwendu_tb = -100;
			chushichafen1_tb = 0;
			chushichafen2_tb = 0;
			lastwendu_tb = tibiaowendu;
			lastchafen_tb = -100;

			chushichafen1_hj = 0;
			lastwendu_hj = huanjingwendu;
			lastchafen_hj = -100;
			chushiwendu_hj = -100;
		}
		if ((int)shijiwendu >= 45 || (int)shijiwendu <= 15)
		{
			shijiwendu = tibiaowendu;
		}
	}
	if (last_chushiwendu_tb != chushiwendu_tb)
	{
		last_tempini_check = 1;                        // 相邻两个时刻的快速升温初始温度值的检查，相同输出0，不同输出1。不同说明升温算法进行了重置，需要重置调度算法中的3分钟计时。
	}
	else
	{
		last_tempini_check = 0;
	}
	last_chushiwendu_tb = chushiwendu_tb;
	return shijiwendu;
}

FastTempResult_t CFastTempHome::wendu(float tibiaowendu, float huanjingwendu, float(*TempBuffPoint)[4], int length, int last, int type_use)
{
	int flat_wendingxing = Stable(TempBuffPoint, length, last);
	float shijiwendu = kuaisushengwen(tibiaowendu, huanjingwendu, type_use);
	FastTempResult_t result;
	result.using_fast_flag = flag;
	result.shijiwendu = shijiwendu;
	result.flat_wendingxing = flat_wendingxing;
	result.chushiwendu_tb = chushiwendu_tb;
	result.flag_error = flag_error;
	result.stage = flag_stage;
	result.last_tempini_check = last_tempini_check;
	return result;
}
